package com.itheima.nio.tomcat.parse;

import com.itheima.nio.tomcat.anno.WebServlet;
import com.itheima.nio.tomcat.exception.IsNotImplementsHttpServletException;
import com.itheima.nio.tomcat.inter.HttpServlet;
import com.itheima.nio.tomcat.inter.PraseServletConfig;
import com.itheima.nio.tomcat.inter.ServletConcurrentHashMap;

import java.io.File;
import java.lang.annotation.Annotation;

/**
 * 作用：解析注解，将标准有@WebServlet这个注解的类对象以及请求的uri存储到ServletConcurrentHashMap.concurrentHashMap
 */
public class AnnoParseServletConfig implements PraseServletConfig {

    // 定义一个servlet路径所对应的常量
    public static final String SERVLET_PATH = "itheima-nio-tomcat\\src\\com\\itheima\\nio\\tomcat\\servlet" ;

    // 定义我们servlet所对应的包名称
    public static final String SERVLET_PACKAGE_NAME = "com.itheima.nio.tomcat.servlet." ;

    @Override
    public void parse() {

        /**
         * 步骤：
         * 1. 将servlet所在的文件路径封装成一个File对象
         * 2. 获取该File对象下所有的文件对应的File对象数组(重点)
         * 3. 遍历这个File对象数组，获取每一个File对象
         * 4. 获取该File对象所对应的名称
         * 5. 然后根据包名称构建对应的类全名
         * 6. 获取该类对应的字节码文件对象
         * 7. 然后判断该类上是否存在WebServlet这个注解，如果存在，执行下一步操作
         * 8. 判断该Servlet所实现的接口中，是否存在HttpServlet接口
         * 9. 如果有就创建该类对象，将其存储到ServletConcurrentHashMap中的ConcurrentHashMap中， 如果没有就抛出自定义异常，将异常信息打印到控制台。
         */

        // 1. 将servlet所在的文件路径封装成一个File对象
        File file = new File(SERVLET_PATH) ;

        // 2. 获取该File对象下所有的文件对应的File对象数组(重点): public File[] listFiles()
        File[] servletFiles = file.listFiles() ;

        // 3. 遍历这个File对象数组，获取每一个File对象
        for(File servletFile : servletFiles) {

            // 4. 获取该File对象所对应的名称
            // String[] split = servletFile.getName().split("\\.");   // .表示的是任意字符意思 ， 我们就想使用.来切割 ， 对.进行转义
            String servletFileName = servletFile.getName().replace(".java" , "");     // AServlet.java

            // 5. 然后根据包名称构建对应的类全名
            String servletFullName = SERVLET_PACKAGE_NAME + servletFileName ;

            try {

                // 6. 获取该类对应的字节码文件对象
                Class servletClazz = Class.forName(servletFullName);

                // 7. 然后判断该类上是否存在WebServlet这个注解，如果存在，执行下一步操作
                if(servletClazz.isAnnotationPresent(WebServlet.class)) {

                    // 8. 判断该Servlet所实现的接口中，是否存在HttpServlet接口
                    boolean flag = false ;                                  // 作用：记录当前这个servlet对象所实现的所有的接口中是否存在HttpServlet接口
                    Class[] interfaces = servletClazz.getInterfaces();
                    for(Class clazz : interfaces) {
                        if(clazz == HttpServlet.class) {
                            flag = true ;
                            break;
                        }
                    }

                    // 判断
                    if(flag) {

                        // 如果有就创建该类对象，将其存储到ServletConcurrentHashMap中的ConcurrentHashMap中
                        HttpServlet httpServlet = (HttpServlet)servletClazz.newInstance() ;

                        // 获取该servlet所对应的请求的uri
                        // public <A extends Annotation> A getAnnotation(Class<A> annotationClass): annotationClass代表的就是指定的注解所对应的字节码文件对象
                        WebServlet webServlet = (WebServlet) servletClazz.getAnnotation(WebServlet.class);
                        String patterns = webServlet.urlPatterns();
                        ServletConcurrentHashMap.concurrentHashMap.put(patterns , httpServlet) ;

                    }else {

                        try {
                            // 如果没有就抛出自定义异常，将异常信息打印到控制台
                            throw  new IsNotImplementsHttpServletException(servletClazz.getName() + " is not implememts HttpServlet interface .....") ;
                        }catch (Exception e) {
                            e.printStackTrace();
                        }

                    }

                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }


}
